#pragma once
#include<lpb_reflect/xvariant/xvariant_Interface.hpp>
#include<map>

template<typename object, typename... types>
struct reflectFactory_createSelf :public object {
	reflectFactory_createSelf(types... args) :object(args...) {}
	static std::shared_ptr<object> crateSelf(types... values) {
		return  std::shared_ptr<object>(new reflectFactory_createSelf<object, types...>(values...));
	}
};

template<typename ctorType>
struct CtorFactory;    

template<typename product, typename... types>
struct CtorFactory<product(types...)> {
	using class_t = product;
	static constexpr decltype(auto) getCreateFn() {
		return &reflectFactory_createSelf<product, types...>::crateSelf;
	}
};

struct __HELP {
	static myVariant reflectFunType(void* pobject,
		myVariant t1 = myVariant(),
		myVariant t2 = myVariant(),
		myVariant t3 = myVariant(),
		myVariant t4 = myVariant(),
		myVariant t5 = myVariant(),
		myVariant t6 = myVariant(),
		myVariant t7 = myVariant(),
		myVariant t8 = myVariant(),
		myVariant t9 = myVariant(),
		myVariant t10 = myVariant()
	) {
		return {};
	}

	static void reflect_setProperty1(void* pobject, myVariant) {}
	static void reflect_setProperty2(myVariant, myVariant) {}

	static myVariant reflect_getProperty1(void* pobject) {}
	static myVariant reflect_getProperty2(myVariant){}

	static myVariant reflectFunType2(myVariant t0,
		myVariant t1 = myVariant(),
		myVariant t2 = myVariant(),
		myVariant t3 = myVariant(),
		myVariant t4 = myVariant(),
		myVariant t5 = myVariant(),
		myVariant t6 = myVariant(),
		myVariant t7 = myVariant(),
		myVariant t8 = myVariant(),
		myVariant t9 = myVariant(),
		myVariant t10 = myVariant()
	) {
		return {};
	}

	static myVariant reflectFactoryFunType(
		myVariant t1 = myVariant(),
		myVariant t2 = myVariant(),
		myVariant t3 = myVariant(),
		myVariant t4 = myVariant(),
		myVariant t5 = myVariant(),
		myVariant t6 = myVariant(),
		myVariant t7 = myVariant(),
		myVariant t8 = myVariant(),
		myVariant t9 = myVariant(),
		myVariant t10 = myVariant()
	) {
		return {};
	}
};

using reflectFunType = decltype(__HELP::reflectFunType);
using reflectFunType2 = decltype(__HELP::reflectFunType2);
using reflectMember_set1 = decltype(__HELP::reflect_setProperty1);
using reflectMember_set2 = decltype(__HELP::reflect_setProperty2);
using reflectMember_get1 = decltype(__HELP::reflect_getProperty1);
using reflectMember_get2 = decltype(__HELP::reflect_getProperty2);
using reflectFactoryFunType = decltype(__HELP::reflectFactoryFunType);
using reflectCstyleFnType = decltype(__HELP::reflectFactoryFunType);

template<typename class_t, typename identifier>
struct reflectContainer{
	inline static std::map<identifier, reflectFunType*> s_memF;
	inline static std::map<identifier, reflectMember_set1*> s_setMem;
	inline static std::map<identifier, reflectMember_get1*> s_getMem;
};

template<typename identifier>
struct reflectContainer<void, identifier> {
	inline static std::map<identifier, reflectFunType2*> s_memF;
	inline static std::map<identifier, reflectMember_set2*> s_setMem;
	inline static std::map<identifier, reflectMember_get2*> s_getMem;
};

template<typename identifier>
struct reflectFactoryContainer {
	inline static std::map<identifier, reflectFactoryFunType*> s_ctorFn;;
};

template<typename identifier>
struct reflectCstyleFnContainer {
	inline static std::map<identifier, reflectCstyleFnType*> s_cstyleFn;;
};

class reflect {
public:
	template< typename destclass, typename ...Args>
	static decltype(auto) Call(std::string id, destclass* pclass, Args...args) {
		auto f = reflectContainer<destclass, std::string>::s_memF.find(id);
		if (f != reflectContainer<destclass, std::string>::s_memF.end()) {
			if constexpr (sizeof...(args) == 0) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),  myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args)  == 1) {
				return f->second(pclass, std::forward<Args>(args)...,
						myVariant(), myVariant(), myVariant(), myVariant(), 
						myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 2) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 3) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 4) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 5) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 6) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 7) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 8) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 9) {
				return f->second(pclass, std::forward<Args>(args)...,
					myVariant());
			}
			if constexpr (sizeof...(args) == 10)
				return f->second(pclass, std::forward<Args>(args)...);
		}
		else {
			std::cout << id << " not register!" << std::endl;
		}
	}

	template< typename ...Args>
	static decltype(auto) Call(std::string id, myVariant obj_varaint, Args...args) {
		auto tmp = obj_varaint;
		auto f = reflectContainer<void,std::string>::s_memF.find(id);
		if (f != reflectContainer<void, std::string>::s_memF.end()) {
			if constexpr (sizeof...(args) == 0) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 1) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 2) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 3) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 4) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 5) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 6) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 7) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 8) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 9) {
				return f->second(obj_varaint, std::forward<Args>(args)...,
					myVariant());
			}
			if constexpr (sizeof...(args) == 10)
				return f->second(obj_varaint, std::forward<Args>(args)...);
		}
		else {
			std::cout << id << " not register!" << std::endl;
		}
	}

	static void set_property(std::string id, myVariant obj_varaint, myVariant t1) {
		auto tmp = obj_varaint;
		auto f = reflectContainer<void, std::string>::s_setMem.find(id);
		if (f != reflectContainer<void, std::string>::s_setMem.end()) {
			f->second(obj_varaint, t1);
		}
		else {
			std::cout << id << " not register!" << std::endl;
		}
	}

	static myVariant get_property(std::string id, myVariant obj_varaint) {
		auto tmp = obj_varaint;
		auto f = reflectContainer<void, std::string>::s_getMem.find(id);
		if (f != reflectContainer<void, std::string>::s_getMem.end()) {
			return f->second(obj_varaint);
		}
		else {
			std::cout << id << " not register!" << std::endl;
			return {};
		}
	}

	template<typename ...Args>
	static decltype(auto) Call_Ansi(std::string id,  Args...args) {
		auto f = reflectCstyleFnContainer<std::string>::s_cstyleFn.find(id);
		if (f != reflectCstyleFnContainer<std::string>::s_cstyleFn.end()) {
			if constexpr (sizeof...(args) == 0) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 1) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 2) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 3) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 4) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 5) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 6) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 7) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 8) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 9) {
				return f->second(std::forward<Args>(args)...,
					myVariant());
			}
			if constexpr (sizeof...(args) == 10)
				return f->second(std::forward<Args>(args)...);
		}
		else {
			std::cout << id << " not register!" << std::endl;
		}
	}

	template<typename ...Args>
	static decltype(auto) Create(std::string id, Args...args) {
		auto f = reflectFactoryContainer<std::string>::s_ctorFn.find(id);
		if (f != reflectFactoryContainer<std::string>::s_ctorFn.end()) {
			if constexpr (sizeof...(args) == 0) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 1) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 2) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 3) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(),
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 4) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 5) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 6) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 7) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 8) {
				return f->second(std::forward<Args>(args)...,
					myVariant(), myVariant());
			}
			if constexpr (sizeof...(args) == 9) {
				return f->second(std::forward<Args>(args)...,
					myVariant());
			}
			if constexpr (sizeof...(args) == 10)
				return f->second(std::forward<Args>(args)...);
		}
		else {
			std::cout << id << " not register!" << std::endl;
		}
	}
public:
	//注册成员函数
	template<auto f>
	static bool registerMemFn(std::string id) {
		using Fn = decltype(f);
		using obj_t =typename NS_variant::getParmType_xvariant<Fn>::class_t;
		reflectContainer<obj_t,std::string>::s_memF.insert(
			{ id,&NS_variant::wrapper_Algorithm<Fn, f>::execute_ptr}
		);

		reflectContainer<void, std::string>::s_memF.insert(
			{ id,&NS_variant::wrapper_Algorithm<Fn, f>::execute_wrapperPtr }
		);
		return true;
	}

	//注册成员变量
	template<auto m>
	static bool registerMember(std::string id) {
		using Fn = decltype(m);
		using obj_t = typename NS_variant::getMemberType<Fn>::class_t;
		reflectContainer<obj_t, std::string>::s_setMem.insert(
			{ id,&NS_variant::wrapper_member<Fn, m>::set_property_ptr }
		);

		reflectContainer<void, std::string>::s_setMem.insert(
			{ id,&NS_variant::wrapper_member<Fn, m>::set_property_wrapperPtr }
		);

		reflectContainer<obj_t, std::string>::s_getMem.insert(
			{ id,&NS_variant::wrapper_member<Fn, m>::get_property_ptr }
		);

		reflectContainer<void, std::string>::s_getMem.insert(
			{ id,&NS_variant::wrapper_member<Fn, m>::get_property_wrapperPtr }
		);
		return true;
	}

	//注册构造函数
	template<typename Ctor>
	static bool registerCtor(std::string className) {
		using obj_t =typename CtorFactory<Ctor>::class_t;
		reflectFactoryContainer<std::string>::s_ctorFn.insert(
			{ className,&NS_variant::wrapper_Algorithm<decltype(CtorFactory<Ctor>::getCreateFn()), CtorFactory<Ctor>::getCreateFn()>::execute_cstyle }
		);
		return true;
	}

	//注册C风格的函数
	template<auto m>
	static bool registerCstyleFn(std::string className) {
		reflectCstyleFnContainer<std::string>::s_cstyleFn.insert(
			{ className,&NS_variant::wrapper_Algorithm<decltype(m), m>::execute_cstyle }
		);
		return true;
	}
};

#define REFLECT_REGISTER_MEMFUN(id,ptrFun) \
reflect::registerMemFn<ptrFun>(id);

#define REFLECT_REGISTER_MEMBER(id,member) \
reflect::registerMember<member>(id);

#define REFLECT_REGISTER_CTOR(objName,...) \
reflect::registerCtor<objName(__VA_ARGS__)>(#objName);

#define REFLECT_REGISTER_CFUN(id,ptrFun) \
reflect::registerCstyleFn<ptrFun>(id);